package eval.utilities.configuration;


import eval.exceptions.ConfigurationException;
import eval.host.HostCapacityEnum;


/**
 * 
 * Configuration file containing all the public fields needed to configure the
 * main aspects of the experiment
 *
 * 
 * 						This an example of configuration file.
 * 						above every variable 
 *
 *			################################################
 *			#			Configuration file				   #
 *			################################################	
 *			
 *			#FIRST - meaning this configuration file have the same definition structure as of 
 *			#all the other tests who have "FIRST" in the beginning of the conf. file. 
 *
 *			#### This number will be part of the result file name, please give a unique value for
 *			#### each experiment in order to identify it. 
 *			confSerialNum = 0
 *			
 *			
 *			####the number of resources in our case: CPU Demand,CPU reservation,Memory.(part of CPLEX input.).
 *			nbResources = 3
 *			
 *			#### ASSUMPTION: the cost of 1 unit of energy is 1$
 *			loadCost = 1
 *
 *			#### Following value is the profit in $ of one provided unit of CPU: 
 *			incomeOnLoad = 3
 *			
 *			
 *			#============CPLEX============
 *			#### the importance of placing VM's
 *			PLACEMENT_WEIGHT = 10000
 *
 *			#### not in use.
 *			RED_LINE_WEIGHT = 3
 *			
 *			#### not in use.
 *			RELOCATION_WEIGHT = 5
 *
 *			#### The importance of not overflowing (modeled as a soft constraint in CPLEX).
 *			CAPACITY_OVERFLOW_WEIGHT = 100000
 *			
 *			#### Permits to enable load balancing in CPLEX (zero value for debug only).
 *			loadBalancingActivated = 1
 *
 *
 *			
 *			#============HOST==========================
 *			#sum of probability on all host should be 1
 *			#==========================================
 *			
 *			#### commands the distribution for host population.(can get the following values 
 *			####RANDOM , CONSTANT(recommended)).
 *
 *			##please note, 	totalNumberOfHosts * hostTypeProbability must be an round number.
 *			hostsTypesDistribution = CONSTANT
 *
 *			#### The Number of hosts in the cloud. 
 *			totalNumberOfHosts = 20
 *			
 *			#### not in use.
 *			HostRedLine = 95
 *
 *			#### set the threshold above which load diminution should be considered. (in % units).
 *			MaxLine = 70
 *
 *			#### the minimum threshold is computed dynamically.
 *			
 *			#--------Small Host----------
 *			smallHostCpuCapacity = 800
 *			smallHostMemCapacity = 1000
 *			smallHostProbability = 0.3
 *
 *			###  for small host we take 40% of the smallHostCpuCapacity
 *			#### The energy consumption when the host is empty. (this value is dynamically computed).
 *			smallhostBaseEnergyConsumption=0
 *
 *			###  we assume that power on consumption is equal to base.
 *			#### The added energy consumption needed for host start up. (this value is dynamically computed).
 *			smallhostPowerOnConsumption=0
 *			
 *			#-------Medium Host----------
 *			mediumHostCpuCapacity = 1500
 *			mediumHostMemCapacity = 2000
 *			mediumHostProbability = 0.4
 *
 *			###  for medium host we take 30% of the mediumHostCpuCapacity.
 *			#### The energy consumption when the host is empty. (this value is dynamically computed).
 *			mediumhostBaseEnergyConsumption=0
 *
 *			###  we assume that power on consumption is equal to base.
 *			#### The added energy consumption needed for host start up. (this value is dynamically computed).
 *			mediumhostPowerOnConsumption=0
 *			
 *			#-------Large Host----------
 *			largeHostCpuCapacity = 3000
 *			largeHostMemCapacity = 3000
 *			largeHostProbability = 0.3
 *
 *			###  for large host we take 20% of the largeHostCpuCapacity.
 *			#### The energy consumption when the host is empty. (this value is dynamically computed).
 *			largehostBaseEnergyConsumption=0
 *
 *			###  we assume that power on consumption is equal to base.
 *			#### The added energy consumption needed for host start up. (this value is dynamically computed).
 *			largehostPowerOnConsumption=0
 *			
 *			#============Virtual Machine==========
 *			#sum of probability on all host should be 1
 *			#=====================================
 *			
 *			#--------Small VM----------
 *			smallVmCpuMin = 40
 *			smallVmCpuMax = 60
 *			smallVmMemMin = 30
 *			smallVmMemMax = 50
 *			smallVmProb = 0.25
 *			
 *			#--------Medium VM----------
 *			mediumVmCpuMin = 80
 *			mediumVmCpuMax = 135
 *			mediumVmMemMin = 80
 *			mediumVmMemMax = 100
 *			mediumVmProb = 0.35 
 *			
 *			#--------Large VM----------
 *			largeVmCpuMin = 220
 *			largeVmCpuMax = 320
 *			largeVmMemMin = 210
 *			largeVmMemMax = 230
 *			largeVmProb = 0.35
 *			
 *			#--------High VM----------
 *			highCpuVmCpuMin = 400
 *			highCpuVmCpuMax = 540
 *			highCpuVmMemMin = 400
 *			highCpuVmMemMax = 410
 *			highCpuVmProb = 0.05 
 *			
 *			
 *			#==========Engine Types================
 *			#	
 *			#		1. OPEN_STACK
 *			#		2. FIRE_FIGHTING
 *			#		3. CPLEX
 *			#=====================================
 *			
 *			#### The number of engines to be tested in this experiment.
 *			numOfEngines = 3
 *
 *			#### The first engine to be run in the experiment.
 *			FirstEngine = CPLEX
 *
 *			#### The second engine to be run in the experiment.
 *			SecondEngine = FIRE_FIGHTING
 *
 *			#### The third engine to be run in the experiment.
 *			ThirdEngine =  OPEN_STACK
 *
 *			#### current running engine. (leave empty).
 *			optimizationGoal
 *			
 *			#==========Compare =============================
 *			#	relevant For OPEN_STACK and FIRE_FIGHTING only 
 *			#		var can be:
 *			#			1. EMPTY_HOST_SORT - no host ordering.
 *			#			2. MAX_HOST_SORT - hosts are ordered by load. (descending load).
 *			#			3. AGE_HOST_SORT - hosts are ordered by decreasing max age of contained VM's. 
 *			#
 *			#	For FireFighiting and OpenStack 
 *			#====================================================
 *			#### The first sort to be used in the experiment.
 *			FirstHeuristic = AGE_HOST_SORT
 *
 *			#### The second sort to be used in the experiment.
 *			SeconHeuristic = AGE_HOST_SORT
 *
 *			#### The third sort to be used in the experiment.
 *			ThirdHeuristick = AGE_HOST_SORT
 *
 *			#### The current sort order used in the test.(leave empty).
 *			heuristicCompareGoal
 *			
 *			
 *			#### not in use.
 *			hostEvaluate = SIMPLE_EVALUATION
 *			
 *			#==========Experiment Ticks================
 *			
 *			#### the experiment length.
 *			experimentTicks = 1000
 *			
 *			#==========Optimization===================
 *			#
 *			#==========================================
 *			## please note, this is not the maximal number of relocation aloud on optimization
 *			## cycle, but the percentage out of the number of (average) vm's
 *			## required to fill the all cloud. the real number of relocation is derived from :
 *			## total cloud capacity, average vm size, and this value below.  
 *			numberOfRelocation = 15
 *
 *			#### The number of cycles between two optimization ticks.(constant value). 
 *			ongoingOptimizationPeriod = 50
 *
 *			
 *			#==========Distribution===================
 *			#### the number of VM's to be deployed on the first cycle..
 *			numberOfInitialVMs = 4
 *
 *			#### The distribution which commands the time interval between two deploy set.
 *			#### (can get the following values: CONSTANT,NORMAL,POISSON).
 *			averageTimeBetweenDeployRequestsDistribution = CONSTANT
 *
 *			#### average for later distribution.
 *			averageTimeBetweenDeployRequests = 8
 *			
 *			#### The distribution which commands the number of Vm's to be deployed in a given set.
 *			####(can get the following values: CONSTANT,NORMAL,POISSON).
 *			## more appropriate name: NumberOfRequestedVMsDistribution
 *			averageNumberOfRequestedVMsDistribution = NORMAL
 *
 *			#### Standard deviation of the above distribution. (relevant for NORMAL dist. only).
 *			averageNumberOfRequestedVMsSTD = 0.5
 *
 *			#### average for later distribution.
 *			averageNumberOfRequestedVMs = 4
 *			
 *			#### The distribution which commands the duration of the low/high demand periods.
 *			####(can get the following values: CONSTANT,NORMAL,POISSON).
 *			## more appropriate name: PeriodDurationDistribution
 *			PeriodAverageDurationDistribution = POISSON
 *
 *			#### average for later distribution.
 *			lowPeriodAverageDuration = 25
 *
 *			#### average for later distribution.
 *			highPeriodAverageDuration = 25
 *			
 *			#### The distribution which commands the life time of each VM.(can get the following 
 *			####values: CONSTANT,NORMAL,POISSON).
 *			##  more appropriate name: deployVMDurationDistribution.
 *			deploySetsDurationDistribution = POISSON
 *
 *			#### Standard deviation of the above distribution. (relevant for NORMAL dist. only).
 *			deploySetAverageDurationSTD = 0.5
 *
 *			#### average for later distribution.
 *			deploySetAverageDuration = 257
 *
 *			
 *			#### given high or low period, following distribution outputs effective demand. 
 *			####(can get the following values: CONSTANT,NORMAL,POISSON).
 *			demandDistribution = NORMAL
 *
 *			#### Standard deviation of the above distribution. (relevant for NORMAL dist. only).
 *			demandDistributionSTD = 0.1
 *
 *			#### not in use.
 *			cpuDemandDistributionVal = 10
 *
 *			#### sets the VM memory demand in case that the above distribution is CONSTANT.
 *			memDemandDistributionVal = 10
 *
 *			
 *
 *			#### the seed for random generator.(if valued 0, dynamically chosen). 
 *			randomSeed = 1
 *			
 *			#input for calculating gradient:
 *			#### gradient is the an indicator of the cloud global load.
 *			##  more appropriate name: gradient history window length.
 *			historyWindowLength = 100
 *
 *			#### This parameter sets for each gradient calculation what will be the length 
 *			####of the X axis (i.e x2-x1).
 *			#### For example in this case we calculate 0.5 * 100 = 50 meaning the gradient width will be 50.
 *			gradientwidth = 0.5
 *
 *			#### we use the following Holt-Winter like formula for softening the demand graph 
 *			####before calculating the gradient:
 *			#### S[t] = alfa * X[t-1] + (1-alfa) * S[t-1] ,  (for 0< t < n) . where alfa = alfaInputForHWalgo.
 *			alfaInputForHWalgo = 0.5
 *
 *			
 *			#==========Log===================
 *			#### When this flag is set, a QA code runs at the end of the test to check some basic
 *			####behavior of the cloud management.
 *			#### In case it finds a problem the error log will be written into the a file under 
 *			####errorLogFilePath.
 *			enableSaintyCheck = true
 *
 *			#### The path to where the file containing the error code of the sanity check is written. 
 *			errorLogFilePath = logs/ValidationResult/
 *
 *			#### The Path to where the result .CSV file is written.
 *			placementLogsPath = logs/placements/
 *
 *			#### The path to the file containing the CPLEX input string of the entire test. 
 *			CplexInputFilePath = logs/cplexInput/input2cplex.txt
 *
 *			#### not in use.
 *			resFile = true
 *
 *			#### not in use.
 *			resFileStr = test1
 *
 *
 *			#====END-======
 *			
 *			##numberOfTickClosingAfterOpening should get the same value as ongoingOptimizationPeriod.
 *			##### This parameter control the time interval in which it's not allowed to close host
 *			##### from the last cycle we've opened a host.  
 *			numberOfTickClosingAfterOpening = 50
 *
 *			#### This parameter control the time delay from which we decide to make host candidate for 
 *			####closing till we allowed to close it.
 *			numberOfTickCandidatesForClosing = 5
 *
 *			
 *			#### This field has be used to give a unique ID for each host when we give each test 3 input files.
 *			#### now, when all engines runs from the same input file, this field is not relevant anymore. 
 *			hostCounter = 0
 *
 *
 *
 * 
 * @author Amit Peled   <amit.kapina@gmail.com>
 * @author Igal Kaufman <igal.kaufman@gmail.com>
 */
public class ExperimentConfiguration extends Configuration {

	private static ExperimentConfiguration singleton;
	public static boolean writeToImgFile =true;
	public int confSerialNum;
	public boolean resFile;
	public String resFileStr;
	public String demandDistribution;
	public double demandDistributionSTD;
	public int cpuDemandDistributionVal;
	public int memDemandDistributionVal;
	public double HostRedLine ;
	public double MaxLine ;
	public int numberOfTickCandidatesForClosing;
	public int numberOfTickClosingAfterOpening;


	/**
	 * Duration of the experiment in cycles
	 * */
	public int experimentTicks;

	/**
	 * Period between two ongoing optimizations
	 * */
	public int ongoingOptimizationPeriod;
	public int numberOfRelocation;
	/**
	 * Total number of host in the system
	 * */
	public int totalNumberOfHosts;
	public String hostsTypesDistribution;

	/**
	 * Number of initial VMs
	 * */
	public int numberOfInitialVMs;
	public int incomeOnLoad;
	public int loadCost;

	/**
	 * HOST CHARACTERISTICS:
	 * */
	// SMALL

	public int smallHostCpuCapacity;
	public int smallHostMemCapacity;
	public double smallHostProbability;
	public int smallhostBaseEnergyConsumption;
	public int smallhostPowerOnConsumption;

	// MEDIUM
	public int mediumHostCpuCapacity;
	public int mediumHostMemCapacity;
	public double mediumHostProbability;
	public int mediumhostBaseEnergyConsumption;
	public int mediumhostPowerOnConsumption;

	// LARGE
	public int largeHostCpuCapacity;
	public int largeHostMemCapacity;
	public double largeHostProbability;
	public int largehostBaseEnergyConsumption;
	public int largehostPowerOnConsumption;

	/**
	 * VM Configurations
	 * */
	// SMALL
	public int smallVmCpuMin;
	public int smallVmCpuMax;
	public int smallVmMemMin;
	public int smallVmMemMax;
	public double smallVmProb;


	// MEDIUM
	public int mediumVmCpuMin;
	public int mediumVmCpuMax;
	public int mediumVmMemMin;
	public int mediumVmMemMax;
	public double mediumVmProb;

	// LARGE
	public int largeVmCpuMin;
	public int largeVmCpuMax;
	public int largeVmMemMin;
	public int largeVmMemMax;
	public double largeVmProb;

	// HIGH CPU
	public int highCpuVmCpuMin;
	public int highCpuVmCpuMax;
	public int highCpuVmMemMin;
	public int highCpuVmMemMax;
	public double highCpuVmProb;


	public String averageTimeBetweenDeployRequestsDistribution;
	public int averageTimeBetweenDeployRequests;
	public String averageNumberOfRequestedVMsDistribution;
	//this is the average number of vm's at the cloud
	//use by DeployGenerator when we extract the total number of vm's at cloud
	public int averageNumberOfRequestedVMs;
	public double averageNumberOfRequestedVMsSTD;
	public String PeriodAverageDurationDistribution;
	public int lowPeriodAverageDuration;
	public int highPeriodAverageDuration;
	public double deploySetAverageDurationSTD;
	public String deploySetsDurationDistribution;
	public int deploySetAverageDuration;
	public int numOfEngines;
	public String optimizationGoal;
	public String FirstEngine;
	public String SecondEngine;
	public String ThirdEngine;
	public String heuristicCompareGoal;	
	public String FirstHeuristic;
	public String SeconHeuristic;
	public String ThirdHeuristick;
	public String hostEvaluate;
	public int randomSeed;
	public boolean enableSaintyCheck;
	public String errorLogFilePath;
	public String placementLogsPath;
	public String CplexInputFilePath;
	// ##### CPLEX VARS #####
	public int PLACEMENT_WEIGHT;
	public int RED_LINE_WEIGHT;
	public int nbResources;
	public int RELOCATION_WEIGHT;
	public int CAPACITY_OVERFLOW_WEIGHT;
	public int loadBalancingActivated;
	//input for calculating gradient:
	public int historyWindowLength;
	public double gradientwidth ;
	public double alfaInputForHWalgo;
	public int hostCounter;



	/**
	 * Set the Base Energy Consumption
	 * 
	 * @param BaseForSmall base value of small
	 * @param BaseForMedium base value of medium
	 * @param BaseForLarge base value of  large
	 */
	public void setHostBaseEnergyConsumption(int BaseForSmall,int BaseForMedium, int BaseForLarge){
		this.smallhostBaseEnergyConsumption = BaseForSmall;
		this.mediumhostBaseEnergyConsumption = BaseForMedium;
		this.largehostBaseEnergyConsumption = BaseForLarge;
	}

	/**
	 * Set the power on Energy Consumption
	 * 
	 * @param BaseForSmall power on value of small
	 * @param BaseForMedium power on value of medium
	 * @param BaseForLarge power on value of  large
	 */
	public void setHostPowerOnConsumption(int PowerOnForSmall, int PowerOnForMedium,int PowerOnForLarge){
		this.smallhostPowerOnConsumption = PowerOnForSmall;
		this.mediumhostPowerOnConsumption = PowerOnForMedium;
		this.largehostPowerOnConsumption = PowerOnForLarge;
	}

	/**
	 * The optimizationGoal
	 * 
	 * @param optimizationGoal
	 */
	public void setOptimizationGoal(String optimizationGoal){
		this.optimizationGoal = optimizationGoal;

	}

	/**
	 * The compare type
	 * 
	 * @param heuristicCompareGoal
	 */
	public void setHeuristicCompareGoal(String heuristicCompareGoal){
		this.heuristicCompareGoal = heuristicCompareGoal;

	}

	/**
	 * seed number
	 * 
	 * @param randomNumber
	 */
	public void setRandomSeed(int randomNumber){
		this.randomSeed = randomNumber;
	}

	/**
	 * Get singleton of Experiment Configuration
	 * 
	 * @return ExperimentConfiguration singleton
	 */
	public static ExperimentConfiguration getSingleton() {
		if (singleton == null) {
			singleton = new ExperimentConfiguration();
		}
		return singleton;
	}

	/**
	 *  get Cloud Capacity
	 * 
	 * @return Cloud Capacity
	 */
	public double getCloudCapacity(){
		return  totalNumberOfHosts * (
				smallHostProbability  * smallHostCpuCapacity +
				mediumHostProbability * mediumHostCpuCapacity +
				largeHostProbability * largeHostCpuCapacity
				);
	}

	/**
	 * get Average VMs CPU Consumption
	 * 
	 * @return Average CPU
	 */
	public double getAverageVMCPUConsumption(){
		return (smallVmProb * ((smallVmCpuMax + smallVmCpuMin)/2) +
				mediumVmProb * ((mediumVmCpuMax + mediumVmCpuMin)/2)+
				largeVmProb * ((largeVmCpuMax + largeVmCpuMin)/2)
				);
	}

	/**
	 * set the MAX number of Relocation allowed at optimization tick
	 * 
	 * @param maxNumberOfRelocation
	 */
	public  void setMaxNumberOfRelocation(int maxNumberOfRelocation){
		this.numberOfRelocation = maxNumberOfRelocation;
	}

	/**
	 * get Start Up Unit Cost by host type
	 * 
	 * @param value the host type
	 * @return Start Up Unit Cost at $
	 */
	public int getStartUpUnitCost(HostCapacityEnum value) {
		switch (value) {
		case SMALL:
			return smallhostPowerOnConsumption;
		case MEDIUM: 
			return mediumhostPowerOnConsumption;
		case LARGE:
			return largehostPowerOnConsumption;
		default:
			throw new IllegalArgumentException(
					"The requested PowerOnConsumption for host is not implemented");
		}
	}

	/**
	 * get base Unit Cost by host type
	 * 
	 * @param value the host type
	 * @return base Unit Cost at $
	 */
	public int getBAseUnitCost(HostCapacityEnum value) {
		switch (value) {
		case SMALL:
			return smallhostBaseEnergyConsumption;
		case MEDIUM: 
			return mediumhostBaseEnergyConsumption;
		case LARGE:
			return largehostBaseEnergyConsumption;
		default:
			throw new IllegalArgumentException(
					"The requested BaseEnergyConsumption for host is not implemented");
		}
	}

	/* (non-Javadoc)
	 * @see eval.utilities.configuration.Configuration#loadFromFile(java.lang.String)
	 */
	@Override
	public void loadFromFile(String filename) throws ConfigurationException /*throws ConfigurationException*/ {
		super.loadFromFile(filename);
	}
}
